
import { createRouter, createWebHashHistory } from "vue-router";
import type { RouteRecordRaw } from "vue-router";
import { App } from "vue";
import { useUserStoreOutside } from "@/store/modules/userStore";
import Cookies from "js-cookie";
import * as http from '@/request/http'
import { homedir } from "os";
import path from "path";


const routes: RouteRecordRaw[] = [
    {
        path: '/login',
        name: 'login',
        component: () => import("@/views/login/index.vue")
    },

    // {
    //     path: '/pms',
    //     component: () => import("@/views/home/index.vue"),
    //     children: [
    //         {
    //             path: 'product',
    //             component: () => import("@/views/pms/product.vue"),
    //         },
    //         {
    //             path: 'addProduct',
    //             component: () => import("@/views/pms/addProduct.vue"),
    //         }
    //     ]
    // }
]

const router = createRouter({
    history: createWebHashHistory(),
    routes,
})


// 全局前置导航守卫
router.beforeEach((to, from, next) => {
    // 路由(非vue文件)中，是不能获取有vue依赖的数据的(如store中的数据)，因此要使用的封装好的经过导出的这个方法获取
    const userStore = useUserStoreOutside();
    //这个要放路由守卫里面，否则获取的不是最新的token
    const token = Cookies.get('token');
    // 刷新菜单栏的逻辑
    // 当页面刷新时，如果已经登录过了，而userStore中menus这个数组没有数据(长度为0)，就重新请求数据，更新数组  并且还是回到当前页面
    if (token && userStore.menus.length === 0) {
        http.admin.getAdminInfoApi().then((res) => {
            if (res.code === 200) {
                // 更新了menus，getters中有依赖这个数据，就会重新执行getters，更新navMenus
                userStore.updateMenus(res.data.menus)
                // ★★动态路由配置★★     
                const navMenus = userStore.genMenusConf;//是一个对象 对象里面的成员是对象  每个对象的成员是数组
                // for in 遍历对象 是可以遍历对象原型链上的属性 如果要严谨一点 可以判断是否是对象自身的属性(hasOwnProperty)
                for (let key in navMenus) {
                    // 这里遍历 要用let 不能用var 
                    if (navMenus.hasOwnProperty(key)) {
                        const dynamicRouteObj: RouteRecordRaw = {
                            path: '/' + navMenus[key].name,
                            name: navMenus[key].name,
                            component: () => import("@/views/home/index.vue"),
                            children: []
                        }
                        navMenus[key].childMenus?.forEach((item) => {
                            dynamicRouteObj.children?.push({
                                path: item.name,
                                name: item.name,
                                // 因为let有自己的块级作用域 当访问的时候 每一次都会有自己的key值依赖  如果是var 只会取最后一个值
                                component: () => import(`@/views/${navMenus[key].name}/${item.name}.vue`),
                            })
                        })
                        router.addRoute(dynamicRouteObj);
                    }
                }
                // 首页是不能在上面routes中配置路由的  因为要获取权限以后才可以访问
                router.addRoute({
                    path: '/',
                    name: 'home',
                    redirect: '/index',
                    component: () => import('@/views/home/index.vue'),
                    children: [
                        {
                            path: 'index',
                            name: 'index',
                            component: () => import('@/views/index/index.vue')
                        }
                    ]
                })
                // 还是回到当前页面 return保证执行到此处不再执行下面的
                // return next();
                // 生成路由规则 要重新执行新的路由，因为添加路由addRoute，并不会触发新的导航，除非触发新的导航，否则不会显示添加的路由
                return next(to.fullPath);
            } else {
                // 如果响应失败，说明是token有问题，清除token，并跳转登录页
                Cookies.remove('token');
                return next('/login')
            }
        })
    } else if (!token && to.path !== '/login') {
        return next('/login');
    } else if (token && to.path === '/login') {
        return next(from)
    } else {
        next()//要跳转的是当前要去的to 
    }
})

/* 
  ★★总结 next跳转机制
  在路由守卫中，只有next()是放行，要去的是当前要跳转到的to(如果是页面刷新,to就是本页面)
  而next('/login)、next(to)、next(...to，replace：true)等等，都不是放行(并不会跳转到这个路由的页面的)，而是 ==> 中断当前导航，执行新的导航
  next('/login)，并不是跳转到/login路由，而是中断这一次的路由守卫的操作，又进一次路由守卫，直到满足条件可以走next()，才会跳转到路由
 */

// 这种方式设置路由  ==>  低耦合
export const initRouter = (app: App<Element>) => {
    app.use(router)
}
